import pymem
import pymem.process
import keyboard
import math
import time
import struct
import ctypes
from ctypes import wintypes
import win32api
import win32con
import win32gui
import threading
import dearpygui.dearpygui as dpg

user32 = ctypes.WinDLL("user32", use_last_error=True)
WDA_NONE = 0x0
WDA_EXCLUDEFROMCAPTURE = 0x11
user32.SetWindowDisplayAffinity.argtypes = [wintypes.HWND, wintypes.DWORD]
user32.SetWindowDisplayAffinity.restype = wintypes.BOOL

def set_anti_capture(hwnd, enable=True):
    flag = WDA_EXCLUDEFROMCAPTURE if enable else WDA_NONE
    return user32.SetWindowDisplayAffinity(hwnd, flag)

class Config:
    show_box = True
    show_bones = True
    show_line = True
    show_head_dot = True
    show_target_count = True
    vertical_offset = 0.0
    aimbot_enabled = False
    aimbot_fov = 100.0
    aimbot_smooth = 3.0
    aimbot_bone = 8
    draw_fov = True
    anti_capture_enabled = False
    aimbot_keybind = "right_mouse"
    box_color = (255, 255, 255)
    bone_color = (255, 255, 255)
    line_color = (255, 255, 255)
    head_color = (255, 255, 255)
    fov_color = (255, 255, 255)
    status = "Not Injected"
    entity_count = 0
    triggerbot_enabled = False
    triggerbot_delay = 0.01
    triggerbot_keybind = "middle_mouse"
    triggerbot_bone = 8
    triggerbot_fov = 50.0
    injected = False
    rgb_time = 0.0

config = Config()

BONE_OPTIONS = ["HEAD", "NECK", "SPINE1", "SPINE2", "SPINE3", "PELVIS"]
BONE_VALUES = [8, 7, 6, 5, 4, 3]
KEYBIND_OPTIONS = {
    "right_mouse": "Right Mouse", "left_mouse": "Left Mouse",
    "middle_mouse": "Middle Mouse", "shift": "Shift", "ctrl": "Control",
    "alt": "Alt", "caps": "Caps Lock", "x1": "Mouse X1", "x2": "Mouse X2"
}

class Offsets:
    ClientEngine = 0x65F7AD0
    EntityList = 0x6E4D0D8
    CAM_POS_X, CAM_POS_Y, CAM_POS_Z = 124, 128, 132
    SCREEN_W, SCREEN_H = 752, 754
    FOV = 824
    ACTOR_INSTANCE = 0x18
    ACTOR_PROPS = 0x278
    ACTOR_COMPONENT = 0x18
    IENTITY = 0x40
    ENTITY_MASK = 0x2E0
    POSE = 0x18
    BIPED_POSE = 0x90
    TRANSFORM = 0x58
    BONE_MATRIX_OFFSET = 0x30
    IGameplay_offset = 0x58
    ClientPlayer_offset = 0x58
    CAMERA_OFFSET = 0x238
    LOCAL_ACTOR_OFFSET = 0x288

class Bones:
    HEAD,NECK,SPINE1,SPINE2,SPINE3,PELVIS=8,7,6,5,4,3
    BUTT_L,BUTT_R=22,18;KNEE_L,KNEE_R=23,19;FOOT_L,FOOT_R=24,20
    SHOULDER_L,SHOULDER_R=14,9;ELBOW_L,ELBOW_R=15,10;WRIST_L,WRIST_R=16,11
    ALL_BONES=[8,7,6,5,4,3,22,18,23,19,24,20,14,9,15,10,16,11]
    CONNECTIONS=[(8,7),(7,6),(6,5),(5,4),(4,3),(6,14),(14,15),(15,16),(6,9),(9,10),(10,11),(3,22),(22,23),(23,24),(3,18),(18,19),(19,20)]

class XMFLOAT3X4:
    def __init__(self,d=None):
        if d and len(d)>=12: self._11,self._12,self._13,self._14,self._21,self._22,self._23,self._24,self._31,self._32,self._33,self._34=d[0:12]
        else: self._11=self._12=self._13=self._14=self._21=self._22=self._23=self._24=self._31=self._32=self._33=self._34=0.0
    @classmethod
    def from_bytes(cls,d):
        if len(d)<48: return cls()
        return cls(struct.unpack('12f',d))

class MathUtils:
    @staticmethod
    def matrix_add(bm,pm):
        ox=(pm._11*bm._32)+(pm._14*bm._33)+(pm._23*bm._34)+pm._32
        oy=(pm._12*bm._32)+(pm._21*bm._33)+(pm._24*bm._34)+pm._33
        oz=(pm._13*bm._32)+(pm._22*bm._33)+(pm._31*bm._34)+pm._34
        return (ox,oy,oz)

class W2S:
    @staticmethod
    def world_to_screen(sdk,cp,wp):
        if cp==0: return None
        try:
            cx=sdk.rpm_float(cp+124);cy=sdk.rpm_float(cp+128);cz=sdk.rpm_float(cp+132)
            rx=wp[0]-cx;ry=wp[1]-cy;rz=wp[2]-cz
            v00=sdk.rpm_float(cp+772);v01=sdk.rpm_float(cp+784);v02=sdk.rpm_float(cp+796)
            v10=sdk.rpm_float(cp+776);v11=sdk.rpm_float(cp+788);v12=sdk.rpm_float(cp+800)
            v20=sdk.rpm_float(cp+780);v21=sdk.rpm_float(cp+792);v22=sdk.rpm_float(cp+804)
            px=rx*v00+ry*v01+rz*v02;py=rx*v10+ry*v11+rz*v12;pz_orig=rx*v20+ry*v21+rz*v22
            if pz_orig>=-0.01: return None
            pz=-pz_orig;fov=sdk.rpm_float(cp+824);f=1.0/math.tan((fov*0.017453292)*0.5)
            sw=float(sdk.rpm_uint16(cp+752));sh=float(sdk.rpm_uint16(cp+754))
            inv_z=1.0/max(abs(pz),0.000001)
            x=round(((px*inv_z)*f*sh+sw)*0.5*10)*0.1;y=round(((sh-((py*inv_z)*f*sh))*0.5)*10)*0.1
            return (x,y)
        except: return None

class SDK:
    def __init__(self): self.pm=None;self.base=0
    def connect(self):
        try: self.pm=pymem.Pymem("BloodStrike.exe");self.base=self.get_module_base("BloodStrike.exe");return True
        except: return False
    def get_module_base(self,n):
        try:
            for m in self.pm.list_modules():
                if m.name.lower()==n.lower(): return m.lpBaseOfDll
        except: pass
        return 0
    def disconnect(self):
        if self.pm:
            try: self.pm.close_process()
            except: pass
            self.pm=None;self.base=0
    def rpm_uint64(self,a):
        try: return self.pm.read_longlong(a)
        except: return 0
    def rpm_float(self,a):
        try: return self.pm.read_float(a)
        except: return 0.0
    def rpm_uint16(self,a):
        try: return self.pm.read_ushort(a)
        except: return 0
    def rpm_bytes(self,a,s):
        try: return self.pm.read_bytes(a,s)
        except: return b'\x00'*s

class Entity:
    def __init__(self): self.address=0;self.position=(0,0,0);self.bone_screen={};self.head_screen=None;self.box_min=None;self.box_max=None;self.is_valid=False

class EntityList:
    @staticmethod
    def get_entities(sdk,cp,lp,la,ss):
        ents=[]
        try:
            el=sdk.rpm_uint64(sdk.base+Offsets.EntityList)
            if not el: return ents
            hd=sdk.rpm_uint64(el+0x8)
            if not hd: return ents
            cur=sdk.rpm_uint64(hd);cnt=0;vis=set()
            while cur and cur!=hd and cnt<2048:
                if cur in vis: break
                vis.add(cur)
                e=EntityList.parse_entity(sdk,cur,cp,lp,la,ss)
                if e and e.is_valid: ents.append(e)
                cur=sdk.rpm_uint64(cur);cnt+=1
        except: pass
        return ents
    
    @staticmethod
    def parse_entity(sdk,addr,cp,lp,la,ss):
        try:
            ai=sdk.rpm_uint64(addr+Offsets.ACTOR_INSTANCE)
            if not ai: return None
            ap=sdk.rpm_uint64(ai+Offsets.ACTOR_PROPS)
            if not ap: return None
            ac=sdk.rpm_uint64(ap+Offsets.ACTOR_COMPONENT)
            if not ac: return None
            ie=sdk.rpm_uint64(ac+Offsets.IENTITY)
            if not ie or ie==la: return None
            em=sdk.rpm_uint64(ie+Offsets.ENTITY_MASK)
            if em!=2: return None
            md=sdk.rpm_bytes(ie+Offsets.TRANSFORM,48);dt=XMFLOAT3X4.from_bytes(md);pos=(dt._14,dt._24,dt._34)
            ps=sdk.rpm_uint64(ai+Offsets.POSE)
            if not ps: return None
            bp=sdk.rpm_uint64(ps+Offsets.BIPED_POSE)
            if not bp: return None
            bp+=0x8
            e=Entity();e.address=ie;e.position=pos;bc=0;ax=[];ay=[]
            for bi in Bones.ALL_BONES:
                bptr=sdk.rpm_uint64(bp+bi*0x8)
                if not(bptr and bptr>0x10000): continue
                bmd=sdk.rpm_bytes(bptr+Offsets.BONE_MATRIX_OFFSET,48)
                if len(bmd)!=48: continue
                bm=XMFLOAT3X4.from_bytes(bmd);bw=MathUtils.matrix_add(bm,dt)
                b2d=W2S.world_to_screen(sdk,cp,bw)
                if not b2d: continue
                bx,by=b2d;e.bone_screen[bi]=b2d;ax.append(bx);ay.append(by);bc+=1
                if bi==Bones.HEAD: e.head_screen=b2d
            if bc<2: return None
            mix=min(ax);may=max(ax);miy=min(ay);mayy=max(ay);w=may-mix;h=mayy-miy
            if w<1 or h<2: return None
            e.box_min=(mix,miy+config.vertical_offset);e.box_max=(may,mayy+config.vertical_offset)
            if not e.head_screen: e.head_screen=e.bone_screen.get(Bones.NECK)
            e.is_valid=True;return e
        except: return None

class Win32Overlay:
    def __init__(self):
        self.hwnd=None;self.hdc=None;self.hdc_mem=None;self.hbm_mem=None
        self.width=win32api.GetSystemMetrics(0);self.height=win32api.GetSystemMetrics(1)
        self.old_gdi=None;self.pens={};self.brushes={};self.active=False
    def create(self):
        try:
            wc=win32gui.WNDCLASS();wc.lpfnWndProc=self._wp;wc.hInstance=win32api.GetModuleHandle(None)
            wc.lpszClassName="YHUJIN_ESP";wc.hCursor=win32gui.LoadCursor(0,win32con.IDC_ARROW);wc.hbrBackground=win32con.COLOR_WINDOW+1
            ca=win32gui.RegisterClass(wc)
            self.hwnd=win32gui.CreateWindowEx(win32con.WS_EX_LAYERED|win32con.WS_EX_TRANSPARENT|win32con.WS_EX_TOPMOST|win32con.WS_EX_NOACTIVATE,ca,"YHUJIN",win32con.WS_POPUP,0,0,self.width,self.height,0,0,wc.hInstance,None)
            set_anti_capture(self.hwnd,config.anti_capture_enabled)
            win32gui.SetLayeredWindowAttributes(self.hwnd,0xFF00FF,0,win32con.LWA_COLORKEY)
            win32gui.ShowWindow(self.hwnd,win32con.SW_SHOW);win32gui.UpdateWindow(self.hwnd)
            self.hdc=win32gui.GetDC(self.hwnd);self.hdc_mem=win32gui.CreateCompatibleDC(self.hdc)
            self.hbm_mem=win32gui.CreateCompatibleBitmap(self.hdc,self.width,self.height)
            self.old_gdi=win32gui.SelectObject(self.hdc_mem,self.hbm_mem)
            self.active=True;return True
        except: return False
    def destroy(self):
        self.active=False
        for p in self.pens.values(): win32gui.DeleteObject(p)
        for b in self.brushes.values(): win32gui.DeleteObject(b)
        self.pens.clear();self.brushes.clear()
        if self.hdc_mem and self.old_gdi: win32gui.SelectObject(self.hdc_mem,self.old_gdi)
        if self.hbm_mem: win32gui.DeleteObject(self.hbm_mem);self.hbm_mem=None
        if self.hdc_mem: win32gui.DeleteDC(self.hdc_mem);self.hdc_mem=None
        if self.hdc and self.hwnd: win32gui.ReleaseDC(self.hwnd,self.hdc);self.hdc=None
        if self.hwnd: win32gui.DestroyWindow(self.hwnd);self.hwnd=None
    def update_anti_capture(self,e):
        if self.hwnd: set_anti_capture(self.hwnd,e)
    def _wp(self,hw,msg,wp,lp):
        if msg==win32con.WM_DESTROY: win32gui.PostQuitMessage(0);return 0
        return win32gui.DefWindowProc(hw,msg,wp,lp)
    def _rgb(self,c): return win32api.RGB(c[0],c[1],c[2])
    def get_pen(self,c,w=1):
        k=(c[0],c[1],c[2],w)
        if k not in self.pens: self.pens[k]=win32gui.CreatePen(win32con.PS_SOLID,w,self._rgb(c))
        return self.pens[k]
    def get_brush(self,c):
        k=(c[0],c[1],c[2])
        if k not in self.brushes: self.brushes[k]=win32gui.CreateSolidBrush(self._rgb(c))
        return self.brushes[k]
    def begin_frame(self):
        if not self.hdc_mem or not self.active: return
        mg=win32gui.CreateSolidBrush(win32api.RGB(255,0,255));win32gui.FillRect(self.hdc_mem,(0,0,self.width,self.height),mg);win32gui.DeleteObject(mg)
    def end_frame(self):
        if self.hdc and self.hdc_mem and self.active: win32gui.BitBlt(self.hdc,0,0,self.width,self.height,self.hdc_mem,0,0,win32con.SRCCOPY)
    def draw_rect(self,x,y,w,h,c,t=2):
        if not self.hdc_mem or not self.active: return
        p=self.get_pen(c,t);op=win32gui.SelectObject(self.hdc_mem,p);nb=win32gui.GetStockObject(win32con.NULL_BRUSH);ob=win32gui.SelectObject(self.hdc_mem,nb)
        win32gui.Rectangle(self.hdc_mem,int(x),int(y),int(x+max(w,1)),int(y+max(h,1)))
        win32gui.SelectObject(self.hdc_mem,op);win32gui.SelectObject(self.hdc_mem,ob)
    def draw_line(self,x1,y1,x2,y2,c,t=1):
        if not self.hdc_mem or not self.active: return
        p=self.get_pen(c,t);op=win32gui.SelectObject(self.hdc_mem,p)
        win32gui.MoveToEx(self.hdc_mem,int(x1),int(y1));win32gui.LineTo(self.hdc_mem,int(x2),int(y2));win32gui.SelectObject(self.hdc_mem,op)
    def draw_circle(self,x,y,r,c,f=False,t=1):
        if not self.hdc_mem or not self.active: return
        if f: b=self.get_brush(c);ob=win32gui.SelectObject(self.hdc_mem,b);np=win32gui.GetStockObject(win32con.NULL_PEN);op=win32gui.SelectObject(self.hdc_mem,np)
        else: p=self.get_pen(c,t);op=win32gui.SelectObject(self.hdc_mem,p);nb=win32gui.GetStockObject(win32con.NULL_BRUSH);ob=win32gui.SelectObject(self.hdc_mem,nb)
        rr=max(int(r),1);win32gui.Ellipse(self.hdc_mem,int(x-rr),int(y-rr),int(x+rr),int(y+rr))
        if f: win32gui.SelectObject(self.hdc_mem,ob);win32gui.SelectObject(self.hdc_mem,op)
        else: win32gui.SelectObject(self.hdc_mem,op);win32gui.SelectObject(self.hdc_mem,ob)

class ESPRenderer:
    def render(self,ov,ents,ss):
        if not ov.hdc_mem or not ov.active: return
        sw,sh=ss;cx=sw//2
        for e in ents:
            if not e.is_valid or not e.box_min: continue
            x1,y1=e.box_min;x2,y2=e.box_max;w,h=x2-x1,y2-y1;mx=(x1+x2)*0.5;vo=config.vertical_offset
            if config.show_box: ov.draw_rect(x1,y1,w,h,config.box_color,2)
            if config.show_bones:
                for a,b in Bones.CONNECTIONS:
                    p1=e.bone_screen.get(a);p2=e.bone_screen.get(b)
                    if p1 and p2: ov.draw_line(p1[0],p1[1]+vo,p2[0],p2[1]+vo,config.bone_color,1)
            if config.show_head_dot and e.head_screen:
                hx,hy=e.head_screen;hy+=vo;hr=max(3,int(h*0.05))
                ov.draw_circle(hx,hy,hr+1,(0,0,0),True);ov.draw_circle(hx,hy,hr,config.head_color,True)
            if config.show_line: ov.draw_line(cx,sh,mx,y2,config.line_color,1)

class Aimbot:
    def __init__(self): self.sc=None
    def is_kp(self):
        m={"right_mouse":0x02,"left_mouse":0x01,"middle_mouse":0x04,"shift":0x10,"ctrl":0x11,"alt":0x12,"caps":0x14,"x1":0x05,"x2":0x06}
        return win32api.GetAsyncKeyState(m.get(config.aimbot_keybind,0))&0x8000
    def run(self,ents,ss):
        if not config.aimbot_enabled or not self.is_kp(): return
        cx,cy=ss[0]//2,ss[1]//2;self.sc=(cx,cy);bt=None;bd=config.aimbot_fov
        for e in ents:
            if not e.is_valid: continue
            t=e.bone_screen.get(config.aimbot_bone) or e.head_screen or e.bone_screen.get(Bones.NECK)
            if t: tx,ty=t;ty+=config.vertical_offset;d=math.sqrt((tx-cx)**2+(ty-cy)**2)
            if d<bd: bd=d;bt=(tx,ty)
        if bt: dx=(bt[0]-cx)/config.aimbot_smooth;dy=(bt[1]-cy)/config.aimbot_smooth;win32api.mouse_event(0x0001,int(dx),int(dy),0,0)
    def draw_fov(self,ov):
        if not config.draw_fov or not self.sc: return
        ov.draw_circle(self.sc[0],self.sc[1],config.aimbot_fov,config.fov_color,False,1)

class TriggerBot:
    def __init__(self): self.lct=0
    def is_kp(self):
        m={"right_mouse":0x02,"left_mouse":0x01,"middle_mouse":0x04,"shift":0x10,"ctrl":0x11,"alt":0x12,"caps":0x14,"x1":0x05,"x2":0x06}
        return win32api.GetAsyncKeyState(m.get(config.triggerbot_keybind,0))&0x8000
    def run(self,ents,ss):
        if not config.triggerbot_enabled or not self.is_kp(): return
        ct=time.time()
        if ct-self.lct<config.triggerbot_delay: return
        cx,cy=ss[0]//2,ss[1]//2
        for e in ents:
            if not e.is_valid: continue
            t=e.bone_screen.get(config.triggerbot_bone) or e.head_screen or e.bone_screen.get(Bones.NECK)
            if t:
                tx,ty=t;ty+=config.vertical_offset
                if math.sqrt((tx-cx)**2+(ty-cy)**2)<=config.triggerbot_fov:
                    win32api.mouse_event(0x0002,0,0,0,0);time.sleep(0.001);win32api.mouse_event(0x0004,0,0,0,0);self.lct=ct;break

class ESPThread(threading.Thread):
    def __init__(self):
        super().__init__(daemon=True)
        self.sdk=None;self.ov=None;self._running=False;self.esp=None;self.aim=None;self.trig=None
        self.ss=(win32api.GetSystemMetrics(0),win32api.GetSystemMetrics(1));self.lac=False
    
    def inject(self):
        if self._running: return False
        self.sdk=SDK()
        if not self.sdk.connect(): self.sdk=None;return False
        self.ov=Win32Overlay()
        if not self.ov.create(): self.sdk.disconnect();self.sdk=None;self.ov=None;return False
        self.esp=ESPRenderer();self.aim=Aimbot();self.trig=TriggerBot()
        self._running=True;self.lac=config.anti_capture_enabled;config.injected=True;config.status="Connected"
        self.start();return True
    
    def uninject(self):
        self._running=False;time.sleep(0.3)
        if self.ov: self.ov.destroy();self.ov=None
        if self.sdk: self.sdk.disconnect();self.sdk=None
        self.esp=None;self.aim=None;self.trig=None
        config.injected=False;config.status="Not Injected";config.entity_count=0
    
    def run(self):
        while self._running:
            try:
                if keyboard.is_pressed('F6'): self._running=False;break
                if self.lac!=config.anti_capture_enabled: self.lac=config.anti_capture_enabled;self.ov.update_anti_capture(self.lac)
                if not self.sdk or not self.sdk.pm: self._running=False;break
                ce=self.sdk.rpm_uint64(self.sdk.base+Offsets.ClientEngine)
                if not ce: time.sleep(0.005);continue
                gp=self.sdk.rpm_uint64(ce+Offsets.IGameplay_offset)
                if not gp: time.sleep(0.005);continue
                cp=self.sdk.rpm_uint64(gp+Offsets.ClientPlayer_offset)
                if not cp: time.sleep(0.005);continue
                cam=self.sdk.rpm_uint64(cp+Offsets.CAMERA_OFFSET);loc=self.sdk.rpm_uint64(cp+Offsets.LOCAL_ACTOR_OFFSET)
                if not cam or not loc: time.sleep(0.005);continue
                mat=self.sdk.rpm_bytes(loc+Offsets.TRANSFORM,48);lmat=XMFLOAT3X4.from_bytes(mat);lpos=(lmat._14,lmat._24,lmat._34)
                ents=EntityList.get_entities(self.sdk,cam,lpos,loc,self.ss)
                config.entity_count=len([e for e in ents if e.is_valid])
                if self.ov and self.ov.active: self.ov.begin_frame();self.esp.render(self.ov,ents,self.ss);self.aim.draw_fov(self.ov);self.ov.end_frame()
                self.aim.run(ents,self.ss);self.trig.run(ents,self.ss);time.sleep(0.005)
            except: time.sleep(0.005)
        self.uninject()

esp_thread = ESPThread()

def get_rgb_color(t):
    r=int((math.sin(t*2.0)*0.5+0.5)*255)
    g=int((math.sin(t*2.0+2.094)*0.5+0.5)*255)
    b=int((math.sin(t*2.0+4.189)*0.5+0.5)*255)
    return(r,g,b,255)

class DearPyGuiMenu:
    def __init__(self):
        dpg.create_context()
        with dpg.theme() as dark_theme:
            with dpg.theme_component(dpg.mvAll):
                dpg.add_theme_style(dpg.mvStyleVar_FrameRounding,3)
                dpg.add_theme_style(dpg.mvStyleVar_GrabRounding,3)
                dpg.add_theme_style(dpg.mvStyleVar_FramePadding,6,3)
                dpg.add_theme_style(dpg.mvStyleVar_ItemSpacing,6,3)
                dpg.add_theme_color(dpg.mvThemeCol_WindowBg,(12,12,12,255))
                dpg.add_theme_color(dpg.mvThemeCol_ChildBg,(16,16,16,255))
                dpg.add_theme_color(dpg.mvThemeCol_FrameBg,(32,32,32,200))
                dpg.add_theme_color(dpg.mvThemeCol_FrameBgHovered,(42,42,42,255))
                dpg.add_theme_color(dpg.mvThemeCol_FrameBgActive,(28,28,28,255))
                dpg.add_theme_color(dpg.mvThemeCol_TitleBg,(22,22,22,255))
                dpg.add_theme_color(dpg.mvThemeCol_Border,(45,45,45,255))
                dpg.add_theme_color(dpg.mvThemeCol_Button,(50,50,50,200))
                dpg.add_theme_color(dpg.mvThemeCol_ButtonHovered,(60,60,60,255))
                dpg.add_theme_color(dpg.mvThemeCol_ButtonActive,(38,38,38,255))
                dpg.add_theme_color(dpg.mvThemeCol_Text,(200,200,200,255))
                dpg.add_theme_color(dpg.mvThemeCol_TextDisabled,(100,100,100,255))
                dpg.add_theme_color(dpg.mvThemeCol_CheckMark,(180,180,180,255))
                dpg.add_theme_color(dpg.mvThemeCol_SliderGrab,(180,180,180,255))
        dpg.bind_theme(dark_theme)
        with dpg.theme() as btn_on:
            with dpg.theme_component(dpg.mvButton): dpg.add_theme_color(dpg.mvThemeCol_Button,(160,160,160,150));dpg.add_theme_color(dpg.mvThemeCol_Text,(0,0,0,255))
        with dpg.theme() as btn_off:
            with dpg.theme_component(dpg.mvButton): dpg.add_theme_color(dpg.mvThemeCol_Button,(50,50,50,200));dpg.add_theme_color(dpg.mvThemeCol_Text,(180,180,180,255))
        self.btn_on=btn_on;self.btn_off=btn_off
        
        dpg.create_viewport(title="IMGUI",width=659,height=505,resizable=True,decorated=True,min_width=640,min_height=480,always_on_top=True)
        dpg.setup_dearpygui()
        
        with dpg.window(tag="main",no_close=True,no_resize=False,no_collapse=True,no_title_bar=False,width=640,height=480):
            with dpg.group(horizontal=True):
                self.title_text=dpg.add_text("Yhujin External",color=(255,0,0,255))
                dpg.add_spacer(width=160)
                self.status_text=dpg.add_text("Not Injected",color=(200,60,60,255))
                dpg.add_spacer(width=30)
                self.inject_btn=dpg.add_button(label="INJECT",width=60,height=20,tag="btn_inject",callback=self.do_inject)
                self.uninject_btn=dpg.add_button(label="UNINJECT",width=65,height=20,tag="btn_uninject",callback=self.do_uninject)
                self.exit_btn=dpg.add_button(label="EXIT",width=45,height=20,callback=self.do_exit)
            dpg.add_separator()
            with dpg.group(horizontal=True):
                self.entity_text=dpg.add_text("0 entities",color=(160,160,160,255))
                dpg.add_spacer(width=350)
                dpg.add_text("F6 Exit | = Min/Max",color=(100,100,100,255))
            dpg.add_spacer(height=4)
            with dpg.group(horizontal=True):
                with dpg.child_window(width=195,height=395,no_scrollbar=True):
                    dpg.add_text("ESP",color=(160,160,160,255));dpg.add_separator()
                    dpg.add_checkbox(label="Box",default_value=True,tag="cb_box")
                    dpg.add_checkbox(label="Bones",default_value=True,tag="cb_bones")
                    dpg.add_checkbox(label="Line",default_value=True,tag="cb_line")
                    dpg.add_checkbox(label="Head Dot",default_value=True,tag="cb_head_dot")
                    dpg.add_checkbox(label="Target Count",default_value=True,tag="cb_target_count")
                    dpg.add_checkbox(label="Anti-Capture",default_value=False,tag="cb_anti_capture")
                    dpg.add_spacer(height=4)
                    dpg.add_text("Offset",color=(120,120,120,255))
                    dpg.add_slider_float(label="##offset",min_value=-100,max_value=100,default_value=0,format="%.0f",tag="sl_offset",width=175)
                    dpg.add_spacer(height=4)
                    dpg.add_text("Colors",color=(120,120,120,255))
                    dpg.add_color_edit(label="##clr_box",default_value=config.box_color,no_alpha=True,tag="clr_box",width=175)
                    dpg.add_color_edit(label="##clr_bone",default_value=config.bone_color,no_alpha=True,tag="clr_bone",width=175)
                    dpg.add_color_edit(label="##clr_line",default_value=config.line_color,no_alpha=True,tag="clr_line",width=175)
                    dpg.add_color_edit(label="##clr_head",default_value=config.head_color,no_alpha=True,tag="clr_head",width=175)
                    dpg.add_color_edit(label="##clr_fov",default_value=config.fov_color,no_alpha=True,tag="clr_fov",width=175)
                dpg.add_spacer(width=6)
                with dpg.child_window(width=200,height=395,no_scrollbar=True):
                    dpg.add_text("Aimbot",color=(160,160,160,255));dpg.add_separator()
                    dpg.add_text("Keybind",color=(120,120,120,255))
                    dpg.add_combo(label="##aim_kb",items=list(KEYBIND_OPTIONS.values()),default_value="Right Mouse",tag="cmb_aim_keybind",width=180)
                    dpg.add_spacer(height=2)
                    dpg.add_text("Bone",color=(120,120,120,255))
                    dpg.add_combo(label="##aim_bone",items=BONE_OPTIONS,default_value="HEAD",tag="cmb_aim_bone",width=180)
                    dpg.add_spacer(height=2)
                    dpg.add_text("FOV",color=(120,120,120,255))
                    dpg.add_slider_float(label="##aim_fov",min_value=10,max_value=300,default_value=100,format="%.0f",tag="sl_aim_fov",width=180)
                    dpg.add_spacer(height=2)
                    dpg.add_text("Smooth",color=(120,120,120,255))
                    dpg.add_slider_float(label="##aim_smooth",min_value=1.0,max_value=10.0,default_value=3.0,format="%.1f",tag="sl_aim_smooth",width=180)
                    dpg.add_spacer(height=2)
                    dpg.add_checkbox(label="Draw FOV Circle",default_value=True,tag="cb_draw_fov")
                    dpg.add_spacer(height=6)
                    self.aimbot_btn=dpg.add_button(label="ENABLE AIMBOT",width=180,height=32,tag="btn_aimbot")
                    dpg.bind_item_theme(self.aimbot_btn,self.btn_off)
                dpg.add_spacer(width=6)
                with dpg.child_window(width=195,height=395,no_scrollbar=True):
                    dpg.add_text("Trigger Bot",color=(160,160,160,255));dpg.add_separator()
                    dpg.add_text("Keybind",color=(120,120,120,255))
                    dpg.add_combo(label="##trig_kb",items=list(KEYBIND_OPTIONS.values()),default_value="Middle Mouse",tag="cmb_trig_keybind",width=175)
                    dpg.add_spacer(height=2)
                    dpg.add_text("Bone",color=(120,120,120,255))
                    dpg.add_combo(label="##trig_bone",items=BONE_OPTIONS,default_value="HEAD",tag="cmb_trig_bone",width=175)
                    dpg.add_spacer(height=2)
                    dpg.add_text("FOV",color=(120,120,120,255))
                    dpg.add_slider_float(label="##trig_fov",min_value=10,max_value=200,default_value=50,format="%.0f",tag="sl_trig_fov",width=175)
                    dpg.add_spacer(height=2)
                    dpg.add_text("Delay",color=(120,120,120,255))
                    dpg.add_slider_float(label="##trig_delay",min_value=1,max_value=100,default_value=10,format="%.0f ms",tag="sl_trig_delay",width=175)
                    dpg.add_spacer(height=4)
                    dpg.add_text("Hold key to auto-fire",color=(100,100,100,255),wrap=175)
                    dpg.add_spacer(height=6)
                    self.trigger_btn=dpg.add_button(label="ENABLE TRIGGER",width=175,height=32,tag="btn_trigger")
                    dpg.bind_item_theme(self.trigger_btn,self.btn_off)
        
        dpg.show_viewport()
        dpg.set_primary_window("main",True)
        self.setup_callbacks()
    
    def do_inject(self):
        if not config.injected: esp_thread.inject()
    def do_uninject(self):
        if config.injected: esp_thread.uninject()
    def do_exit(self):
        if config.injected: esp_thread.uninject()
        dpg.stop_dearpygui()
    
    def setup_callbacks(self):
        dpg.set_item_callback("cb_box",lambda s,a,u:setattr(config,'show_box',a))
        dpg.set_item_callback("cb_bones",lambda s,a,u:setattr(config,'show_bones',a))
        dpg.set_item_callback("cb_line",lambda s,a,u:setattr(config,'show_line',a))
        dpg.set_item_callback("cb_head_dot",lambda s,a,u:setattr(config,'show_head_dot',a))
        dpg.set_item_callback("cb_target_count",lambda s,a,u:setattr(config,'show_target_count',a))
        dpg.set_item_callback("cb_anti_capture",lambda s,a,u:setattr(config,'anti_capture_enabled',a))
        dpg.set_item_callback("sl_offset",lambda s,a,u:setattr(config,'vertical_offset',a))
        dpg.set_item_callback("clr_box",lambda s,a,u:setattr(config,'box_color',a))
        dpg.set_item_callback("clr_bone",lambda s,a,u:setattr(config,'bone_color',a))
        dpg.set_item_callback("clr_line",lambda s,a,u:setattr(config,'line_color',a))
        dpg.set_item_callback("clr_head",lambda s,a,u:setattr(config,'head_color',a))
        dpg.set_item_callback("clr_fov",lambda s,a,u:setattr(config,'fov_color',a))
        dpg.set_item_callback("cmb_aim_keybind",lambda s,a,u:setattr(config,'aimbot_keybind',list(KEYBIND_OPTIONS.keys())[list(KEYBIND_OPTIONS.values()).index(a)]))
        dpg.set_item_callback("cmb_aim_bone",lambda s,a,u:setattr(config,'aimbot_bone',BONE_VALUES[BONE_OPTIONS.index(a)]))
        dpg.set_item_callback("sl_aim_fov",lambda s,a,u:setattr(config,'aimbot_fov',a))
        dpg.set_item_callback("sl_aim_smooth",lambda s,a,u:setattr(config,'aimbot_smooth',a))
        dpg.set_item_callback("cb_draw_fov",lambda s,a,u:setattr(config,'draw_fov',a))
        dpg.set_item_callback("btn_aimbot",self.toggle_aimbot)
        dpg.set_item_callback("cmb_trig_keybind",lambda s,a,u:setattr(config,'triggerbot_keybind',list(KEYBIND_OPTIONS.keys())[list(KEYBIND_OPTIONS.values()).index(a)]))
        dpg.set_item_callback("cmb_trig_bone",lambda s,a,u:setattr(config,'triggerbot_bone',BONE_VALUES[BONE_OPTIONS.index(a)]))
        dpg.set_item_callback("sl_trig_fov",lambda s,a,u:setattr(config,'triggerbot_fov',a))
        dpg.set_item_callback("sl_trig_delay",lambda s,a,u:setattr(config,'triggerbot_delay',a/1000.0))
        dpg.set_item_callback("btn_trigger",self.toggle_trigger)
    
    def toggle_aimbot(self):
        config.aimbot_enabled=not config.aimbot_enabled
        if config.aimbot_enabled: dpg.set_item_label("btn_aimbot","DISABLE AIMBOT");dpg.bind_item_theme("btn_aimbot",self.btn_on)
        else: dpg.set_item_label("btn_aimbot","ENABLE AIMBOT");dpg.bind_item_theme("btn_aimbot",self.btn_off)
    def toggle_trigger(self):
        config.triggerbot_enabled=not config.triggerbot_enabled
        if config.triggerbot_enabled: dpg.set_item_label("btn_trigger","DISABLE TRIGGER");dpg.bind_item_theme("btn_trigger",self.btn_on)
        else: dpg.set_item_label("btn_trigger","ENABLE TRIGGER");dpg.bind_item_theme("btn_trigger",self.btn_off)
    
    def update_status(self):
        config.rgb_time+=0.016
        rgb=get_rgb_color(config.rgb_time)
        dpg.configure_item(self.title_text,color=rgb)
        if config.injected: c=(60,200,60,255);s="Connected"
        else: c=(200,60,60,255);s="Not Injected"
        dpg.set_value(self.status_text,s);dpg.configure_item(self.status_text,color=c)
        dpg.set_value(self.entity_text,f"{config.entity_count} entities")
        dpg.configure_item("btn_inject",enabled=not config.injected)
        dpg.configure_item("btn_uninject",enabled=config.injected)
    
    def render(self): self.update_status();dpg.render_dearpygui_frame()
    
    def should_close(self):
        if not dpg.is_dearpygui_running():
            if config.injected: esp_thread.uninject()
            return True
        return False
    def destroy(self): dpg.destroy_context()

if __name__=="__main__":
    menu=DearPyGuiMenu()
    while not menu.should_close(): menu.render();time.sleep(0.016)
    menu.destroy()